use eframe::{egui::{self, Context, Layout, Ui}, App};
use poll_promise::Promise;
use serde_json::Value;

#[tokio::main]
async fn main() -> eframe::Result {
    let options = eframe::NativeOptions {
        viewport: egui::ViewportBuilder::default().with_inner_size([500.0, 240.0]),
        ..Default::default()
    };
    eframe::run_native(
        "Translation",
        options,
        Box::new(|cc| {
            Ok(Box::new(Application::new(cc)))
        }),
    )
}
#[derive(PartialEq,Debug,Clone)]
enum Language {
    ZH,
    EN,
}
struct Application{
    source_lang:Language,
    source_text:String,
    target_lang:Language,
    target_text:String,
    promise: Option<Promise<ehttp::Result<ehttp::Response>>>,
}

impl Application {
    fn new(cc: &eframe::CreationContext<'_>)-> Self {
        Application::load_font(&cc.egui_ctx);
        Application{
            source_lang:Language::ZH,
            target_lang:Language::EN,
            source_text:String::new(),
            target_text:String::new(),
            promise:None
        }
    }
    fn load_font(ctx: &egui::Context) {
        let mut fonts = egui::FontDefinitions::default();
        fonts.font_data.insert(
            "my_font".to_owned(),
            egui::FontData::from_static(include_bytes!("./AlimamaFangYuanTi.ttf")),
        );
        fonts.families.entry(egui::FontFamily::Proportional).or_default().insert(0, "my_font".to_owned());
        fonts.families.entry(egui::FontFamily::Monospace).or_default().push("my_font".to_owned());
        ctx.set_fonts(fonts);
    }
    fn translation_body(&self) -> Vec<u8> {
        let value = serde_json::json!({
            "header": {
              "fn": "auto_translation",
              "client_key":"browser-chrome",
              "session": "",
              "user": ""
            },
            "type": "plain",
            "model_category": "normal",
            "text_domain": "general",
            "source": {
              "lang": format!("{:#?}",self.source_lang),
              "text_list": [
                "",
                self.source_text,
                ""
              ]
            },
            "target": {
              "lang": format!("{:#?}",self.target_lang)
            }
          });
          serde_json::to_vec(&value).unwrap()
    }
    fn translation(&mut self,ctx: &Context){
        let ctx = ctx.clone();
        let (sender, promise) = Promise::new();
        let request = ehttp::Request::post("https://transmart.qq.com/api/imt",self.translation_body());
        ehttp::fetch(request, move |result: ehttp::Result<ehttp::Response>| {
            ctx.request_repaint();
            let resource = result.map(|response| response);
            sender.send(resource);
        });
        self.promise = Some(promise);
    }
    fn language_select_layout(&mut self,ui:&mut Ui,ctx: &Context){
        ui.horizontal(|ui| {
            egui::ComboBox::from_label("Source")
            .selected_text(format!("{:#?}",self.source_lang))
            .show_ui(ui, |ui|{
                ui.selectable_value(&mut self.source_lang, Language::ZH, "ZH");
                ui.selectable_value(&mut self.source_lang, Language::EN, "EN");
            });
            
            egui::ComboBox::from_label("Target")
            .selected_text(format!("{:#?}",self.target_lang))
            .show_ui(ui, |ui|{
                ui.selectable_value(&mut self.target_lang, Language::ZH, "ZH");
                ui.selectable_value(&mut self.target_lang, Language::EN, "EN");
            });

            if ui.button("Interchange").clicked() {
                let temp_source_lang = self.source_lang.clone();
                self.source_lang = self.target_lang.clone();
                self.target_lang = temp_source_lang;
            }

            if ui.button("Translation").clicked() {
                self.translation(ctx);
            }

            if let Some(promise) = &self.promise {
                if let Some(result) = promise.ready() {
                    match result {
                        Ok(response) => {
                            let object:Option<Value> = match serde_json::from_str(response.text().unwrap()){
                                Ok(value) => Some(value),
                                Err(err) => {
                                    ui.label(err.to_string());
                                    None
                                }
                            };

                            if let Some(value) = object {
                                self.target_text = value["auto_translation"][1].to_string();
                            }
                        }
                        Err(err) => {
                            ui.label(err);
                        }
                    }
                }
            }
        });
    }
    fn text_edit_layout(&mut self,ui:&mut Ui){
        ui.with_layout(Layout::top_down_justified(egui::Align::Center), |ui|{
            egui::ScrollArea::vertical().show(ui, |ui| {
                ui.add(
                    egui::TextEdit::multiline(&mut self.source_text).desired_rows(10)
                );
                ui.label(&self.target_text);
            });
        });
    }
}

impl App for Application {
    fn update(&mut self, ctx: &egui::Context, _: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui|{
            self.language_select_layout(ui,ctx);
            ui.separator();
            self.text_edit_layout(ui);
        });
    }
}

